#include <iostream>
#include <vector>
#include <string>
//#include "iostream"
#include<iomanip> 
#include <time.h>
#include "recursion.h"
#include <chrono>
#define setbit(x,y)  (x|=(1<<y)) //let the y bit be 1  
#define twosetbit(x,y,z) (x|=((1<<y)|(1<<z)))
#define clrbit(x,y)  (x&=~(1<<y)) //let the y bit be 0
#define twoclrbit(x,y,z) (x&=~((1<<y)|(1<<z)) )
#define reversebit(x,y)  (x^=(1<<y)) //reverse the y bit
#define getbit(x,y)   ((x) >> (y)&1) //get the y bit number begin with the 0 bit
using namespace std;
 unsigned long long int SequenceLowEnergy1;
 double currentenergy1=1000;
//extern long int count;
struct Node
{
    unsigned long long int Sequence;
    int CurrentLeft;
    int CurrentRight;
    int CurrentLayer;
    double CurrentLowEnergy;
    int SequenceLength;
};
Node node[1024];
inline void SetNode(int IndicatorLocation,unsigned long long int Sequence,int CurrentLeft,int CurrentRight,int CurrentLayer,int SequenceLength){

node[IndicatorLocation].CurrentLayer=CurrentLayer;
node[IndicatorLocation].CurrentLeft=CurrentLeft;
node[IndicatorLocation].CurrentRight=CurrentRight;
node[IndicatorLocation].Sequence=Sequence;
node[IndicatorLocation].SequenceLength=SequenceLength;
}

double NotRecursin(unsigned long long int Sequence,int CurrentLeft,int CurrentRight,int CurrentLayer,double CurrentLowEnergy,int SequenceLength)
{
node[1].Sequence=Sequence;
node[1].CurrentLeft=CurrentLeft;
node[1].CurrentRight=CurrentRight;
node[1].CurrentLayer=CurrentLayer;
node[1].SequenceLength=SequenceLength;
int IndicatorLocation=1;
while(IndicatorLocation!=0){
    //if not leaf node execute cut branch algorithm

    if(node[IndicatorLocation].CurrentLeft>node[IndicatorLocation].CurrentRight+2){
        
        SetNode(IndicatorLocation,node[IndicatorLocation].Sequence,node[IndicatorLocation].CurrentLeft-1,1+node[IndicatorLocation].CurrentRight,1+ node[IndicatorLocation].CurrentLayer,SequenceLength);
        SetNode(IndicatorLocation+1,setbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentLeft)), node[IndicatorLocation].CurrentLeft,node[IndicatorLocation].CurrentRight,node[IndicatorLocation].CurrentLayer,SequenceLength);
        clrbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentLeft));
        SetNode(IndicatorLocation+2,setbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentRight)),node[IndicatorLocation].CurrentLeft,node[IndicatorLocation].CurrentRight,node[IndicatorLocation].CurrentLayer,SequenceLength);

        SetNode(IndicatorLocation+3,twosetbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentLeft),(node[IndicatorLocation].CurrentRight)),node[IndicatorLocation].CurrentLeft,node[IndicatorLocation].CurrentRight,node[IndicatorLocation].CurrentLayer,SequenceLength);
        twoclrbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentLeft),(node[IndicatorLocation].CurrentRight));
        IndicatorLocation+=3;
    }
    else if(node[IndicatorLocation].CurrentLeft==node[IndicatorLocation].CurrentRight+2){
        SetNode(IndicatorLocation,node[IndicatorLocation].Sequence,node[IndicatorLocation].CurrentLeft-1,node[IndicatorLocation].CurrentRight,node[IndicatorLocation].CurrentLayer+1,SequenceLength);
        SetNode(IndicatorLocation+1,setbit(node[IndicatorLocation].Sequence,(node[IndicatorLocation].CurrentLeft)),node[IndicatorLocation].CurrentLeft,node[IndicatorLocation].CurrentRight,node[IndicatorLocation].CurrentLayer,SequenceLength);
        clrbit(node[IndicatorLocation].Sequence,node[IndicatorLocation].CurrentLeft);
        IndicatorLocation++;
    }
    else{
        double Energy=0;
        int Autocorrelations=0;;
        for(int i=0;i<node[IndicatorLocation].SequenceLength;i++){
            for(int j=0;j<node[IndicatorLocation].SequenceLength-i;j++){
                int ii=(getbit(node[IndicatorLocation].Sequence,j));
                int jj=(getbit(node[IndicatorLocation].Sequence,(j+i)));
                 if((ii==1)&&(jj==0)||((ii==0)&&(jj==1))){
            Autocorrelations=Autocorrelations-2;
            //Autocorrelations--;
        }
        Autocorrelations++;

            }
            Energy=Energy+Autocorrelations*Autocorrelations;
            Autocorrelations=0;
        }
         Energy=Energy-SequenceLength*SequenceLength;
       if(Energy<currentenergy1){

        CurrentLowEnergy=Energy;
       currentenergy1=Energy;
        SequenceLowEnergy1=Sequence;
        

    }
    IndicatorLocation--;
}    //ELSE

}
//cout<<"eeeeee::"<<SequenceLowEnergy1<<endl;
return currentenergy1;
}
